﻿using System;
//语言绑定是在一个动态对象未实现IDynamicMetaObjectProvider时出现的。
//语言绑定在处理设计不当的类型或.NET类型系统内在限制时是非常有用的。
//使用数字类型的一个常见问题是它们没有通用接口。我们已经知道是可以动态绑定的，运算符也一样可以动态绑定：
namespace _131_动态绑定_语言绑定
{
    class Program
    {
        static dynamic Mean(dynamic x, dynamic y)
        {
            return (x + y) / 2;
        }

        static void Main(string[] args)
        {
            int x = 3, y = 4;
            Console.WriteLine(Mean(x, y));
            //其明显的好处是，不需要重复地处理每种数字类型。
            //然而会因此影响静态类型安全性以及可能会遇到运行时异常，而不是编译时错误。

            //提示：动态绑定会损坏静态类型安全性，但不会影响运行时类型安全性。于反射机制不同，不能通过动态绑定绕过成员访问规则。

            //通过特殊设计，语言运行时绑定可以无限接近静态绑定的效果，使动态对象的运行时类型能够在编译时确定。
            //在前一个例子中，如果我们在Mean代码中直接处理int类型，那么程序的行为是相同的。静态和动态绑定之间最显著的差异在于扩展方法，在“不可调用函数”中对进行介绍。

            //提示：动态绑定也会对性能产生影响。然而，由于DLR的缓存机制对同一个动态表达式的重复调用进行了优化，允许在一个循环中高效地调用动态表达式。这个优化机制能够使一个简单的动态表达式的处理负载对硬件的性能影响控制在100ms以内。

            //4.11.4 RuntimeBinderException
            //如果一个成员绑定失败，那么程序会抛出RuntimeBinderException异常。可以将它看作是一个运行时的编译错误：
            dynamic d = 5;
            d.Hello(); // 抛出RuntimeBinderException
            //抛出异常的原因是int类型没有Hello方法
            Console.ReadKey();
        }
    }
}
